package org.stars.dao.sqlmapper;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.simpleframework.xml.Attribute;
import org.simpleframework.xml.ElementList;
import org.simpleframework.xml.Root;
import org.simpleframework.xml.core.Commit;
import org.simpleframework.xml.core.Validate;
import org.stars.dao.exception.DuplicateIdFoundException;
import org.stars.datastructure.map.CaseInsensitiveHashMap;

import static org.stars.config.Message.SQL_MAPPER_IMPL_01;
import static org.stars.config.Message.SQL_MAPPER_IMPL_02;

@Root(name = "sqlMapper")
public class SqlMapperImpl implements SqlMapper {
	
	protected String source;

	@Attribute(name = "id")
	protected String id;
	
	@Attribute(name = "paramType", required=false)
	protected String defaultParamType;
	
	@Attribute(name = "resultType", required=false)
	protected String defaultResultType;

	@ElementList(inline = true, entry = "select", required = false)
	protected List<SqlSelect> selectList;

	@ElementList(inline = true, entry = "insert", required = false)
	protected List<SqlInsert> insertList;

	@ElementList(inline = true, entry = "update", required = false)
	protected List<SqlUpdate> updateList;

	@ElementList(inline = true, entry = "delete", required = false)
	protected List<SqlDelete> deleteList;

	@ElementList(inline = true, entry = "call", required = false)
	protected List<SqlProcedure> procedureList;

	@ElementList(inline = true, entry = "fragment", required = false)
	protected List<SqlFragment> fragmentList;

	public SqlMapperImpl() {
		insertList = new ArrayList<SqlInsert>();
		updateList = new ArrayList<SqlUpdate>();
		selectList = new ArrayList<SqlSelect>();
		deleteList = new ArrayList<SqlDelete>();
		procedureList = new ArrayList<SqlProcedure>();
		fragmentList = new ArrayList<SqlFragment>();
		source="";

		map = new CaseInsensitiveHashMap<SqlDefinition>();
	}

	protected Map<String, SqlDefinition> map;

	/* (non-Javadoc)
	 * @see org.stars.dao.sqlmapper.SqlMapper#getInsertList()
	 */
	@Override
	public List<SqlInsert> getInsertList() {
		return insertList;
	}

	public void setInsertList(List<SqlInsert> insertList) {
		this.insertList = insertList;
	}

	/* (non-Javadoc)
	 * @see org.stars.dao.sqlmapper.SqlMapper#getUpdateList()
	 */
	@Override
	public List<SqlUpdate> getUpdateList() {
		return updateList;
	}

	public void setUpdateList(List<SqlUpdate> updateList) {
		this.updateList = updateList;
	}

	/* (non-Javadoc)
	 * @see org.stars.dao.sqlmapper.SqlMapper#getProcedureList()
	 */
	@Override
	public List<SqlProcedure> getProcedureList() {
		return procedureList;
	}

	public void setProcedureList(List<SqlProcedure> procedureList) {
		this.procedureList = procedureList;
	}

	/* (non-Javadoc)
	 * @see org.stars.dao.sqlmapper.SqlMapper#getFragmentList()
	 */
	@Override
	public List<SqlFragment> getFragmentList() {
		return fragmentList;
	}

	public void setFragmentList(List<SqlFragment> fragmentList) {
		this.fragmentList = fragmentList;
	}

	/**
	 * Validation on load. Executed before complete
	 */
	@Validate
	protected void complete() throws Exception {
		Log logger = LogFactory.getLog(getClass());
		String key;

		Object[] liste = { this.selectList, this.fragmentList, this.insertList, this.procedureList, this.updateList,
				this.deleteList };

		for (Object item0 : liste) {
			@SuppressWarnings("unchecked")
			List<? extends SqlDefinition> lista = (List<? extends SqlDefinition>) item0;

			for (SqlDefinition item : lista) {
				key = item.getId().toLowerCase();
				if (map.containsKey(key)) {
					throw (new DuplicateIdFoundException(this, key));
				} else {
					map.put(item.getId(), item);
				}
			}

		}

		logger.debug(SQL_MAPPER_IMPL_01.with(id));
	}

	@Commit
	protected void commit() {
		Log logger = LogFactory.getLog(getClass());

		logger.debug(SQL_MAPPER_IMPL_02.with(selectList.size(),id));
	}

	/* (non-Javadoc)
	 * @see org.stars.dao.sqlmapper.SqlMapper#getSelectList()
	 */
	@Override
	public List<SqlSelect> getSelectList() {
		return selectList;
	}

	public void setSelectList(List<SqlSelect> selectList) {
		this.selectList = selectList;
	}

	/* (non-Javadoc)
	 * @see org.stars.dao.sqlmapper.SqlMapper#getMap()
	 */
	@Override
	public Map<String, SqlDefinition> getMap() {
		return map;
	}

	public void setMap(Map<String, SqlDefinition> map) {
		this.map = map;
	}

	/* (non-Javadoc)
	 * @see org.stars.dao.sqlmapper.SqlMapper#getId()
	 */
	@Override
	public String getId() {
		return id;
	}

	public void setId(String id) {
		this.id = id;
	}

	/* (non-Javadoc)
	 * @see org.stars.dao.sqlmapper.SqlMapper#getDeleteList()
	 */
	@Override
	public List<SqlDelete> getDeleteList() {
		return deleteList;
	}

	public void setDeleteList(List<SqlDelete> deleteList) {
		this.deleteList = deleteList;
	}

	@Override
	public String getSource() {
		return source;		
	}

	@Override
	public void setSource(String value) {
		source=value;
	}

	@Override
	public String getDefaultParamType() {
		return defaultParamType;
	}

	@Override
	public String getDefaultResultType() {
		return defaultResultType;
	}

}
